Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RBAC tweaks #250

Merged
merged 7 commits into from
May 31, 2024
Merged

RBAC tweaks #250

merged 7 commits into from
May 31, 2024

Conversation

andrewplummer
Copy link
Collaborator

@andrewplummer andrewplummer commented Apr 29, 2024

Motivation

Basic motivation here is to "flatten" out RBAC permissions in order to make them more generic, action-based, and human readable. The assumption of different "levels" (ie. ReadWrite -> Write -> Read) is instead replaced with generic tokens that can be enumerated in an array, allowing different actions to be easily added and scanned within roles.json. For example:

// before
{
    "name": "Admin",
    "permissions": {
      "appointments": "read-write",
    }
}
// after
{
    "name": "Admin",
    "permissions": {
      "appointments": [
        "create",
        "update",
        "reschedule",
        "delete"
      ]
    }
}

This allows complex route-based actions like "rescheduling" to be represented as specific, named permissions in roles so that it's easy to see which users can do what. Note also here that create, update, and delete are also arbitrary and represent the maximum possible granularity. For endpoints that aren't as sensitive this could simply be edit, or even any - the meaning of the tokens is left up to the implementer and where/how they use them in the routes middleware.

Additionally for brevity the token all is introduced as a shortcut to allow all permissions:

// after
{
    "name": "Super Admin",
    "permissions": {
      "products": "all",
      "shops": "all",
      "users": "all"
    }
}

Middleware Shortcuts

The middleware also now allows shortcuts that make adding permission checks simpler:

// routes/invites.js
router
  .post('/',
    requirePermissions('users.invite'),
    async (ctx) => {
      // ..
    }
  )

The middleware functionality itself is the same, ie. it can be applied to each route or cascade with .use.

Multi-Tenancy

As multi-tenancy is often layered in after a project has gained maturity, a few tweaks were made to assume global scope out of the box. However this is also now more easily tweaked later:

// src/utils/middleware/permissions.js

// This can be changed to "organization" to quickly enable
// multi-tenancy. Be sure when doing this to lock down global
// permissions such as searching all users, impersonation, etc.
const DEFAULT_SCOPE = 'global';

Note that the grunt work of adding organization fields to each model, filtering searches by org etc remain the same. Streamlining that (if necessary) is left as out of scope for this PR.

Also note:

I need some input on the motivation behind permissions.json as that will need to be updated to fit in here.

@andrewplummer andrewplummer merged commit 3e25883 into master May 31, 2024
2 checks passed
@andrewplummer andrewplummer deleted the rbac-tweaks branch May 31, 2024 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant